package top.lywivan.reggie.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import top.lywivan.reggie.service.CategoryService;
import top.lywivan.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/dish")
@Slf4j
public class DishController {
    @Autowired
    private DishService dishService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private DishFlavorService dishFlavorService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 用于添加菜品，需要包括保存口味信息
     * @param dishDto 前端传入的要保存的对象
     * @return
     */
    @PostMapping
    //springcache实现数据一致,allEntries = true表示删除所有value开头的键
    @CacheEvict(value = "dish",key = "#dishDto.categoryId")
    public R save(@RequestBody DishDto dishDto){
        dishService.saveWithFlavors(dishDto);
        return R.success("保存成功");
    }

    /**
     * 分页查询菜品，由于需要返回分类名称，所以封装为dto对象返回
     * @param page 当前页
     * @param pageSize 每页显示条数
     * @param name 模糊搜索条件
     * @return
     */
    @GetMapping("/page")
    public R page(@RequestParam(required = false,defaultValue = "1")Long page,@RequestParam(required = false,defaultValue = "10")Long pageSize,String name){
        log.info("开始进行分页查询，当前页：{}，每页条数：{}，模糊查询条件：{}",page,pageSize,name);
        Page<Dish> dishPage = dishService.page(new Page<Dish>(page, pageSize), Wrappers.<Dish>lambdaQuery().like(name != null, Dish::getName, name).orderByDesc(Dish::getUpdateTime));
        Page<DishDto> dishDtoPage = new Page<>();
        BeanUtils.copyProperties(dishPage,dishDtoPage);
        List<Dish> dishList = dishPage.getRecords();
        //stream流实现将dish对象，转化为dishFlavor对象
        List<DishDto> dishDtoList = dishList.stream().map(dish -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish, dishDto);
            dishDto.setCategoryName(categoryService.getById(dish.getCategoryId()).getName());
            return dishDto;
        }).collect(Collectors.toList());
        dishDtoPage.setRecords(dishDtoList);
        return R.success(dishDtoPage);
    }

    /**
     * 根据id查询菜品对象，用于数据回显，需要查询出相关的口味信息，因此需要使用Dto封装后返回
     * @param id 要查询的菜品id
     * @return
     */
    @GetMapping("/{id}")
    public R getById(@PathVariable("id") Long id){
        DishDto dishDto = dishService.getByIdWithDishFlavor(id);
        return R.success(dishDto);
    }

    /**
     * 根据id修改菜品信息，需要修改菜品的相关口味信息，因此需要自定义方法
     * @param dishDto 要修改的菜品信息
     * @return
     */
    @PutMapping
    //springcache实现数据一致,allEntries = true表示删除所有value开头的键
    @CacheEvict(value = "dish",key = "#dishDto.categoryId")
    public R update(@RequestBody DishDto dishDto){
        dishService.updateWithDishFlavor(dishDto);
        //原生redis实现数据同步，需要保证数据一致性
        //redisTemplate.delete("dish:"+dishDto.getCategoryId());
        return R.success("修改成功！");
    }

    /**
     * 用于更新菜品的状态属性（可以批量）
     * @param status 要更新的状态
     * @param ids 要更新的菜品id数组
     * @return
     */
    @PostMapping("/status/{status}")
    public R updateStatus(@PathVariable("status")Integer status,Long[] ids){
        dishService.update(Wrappers.<Dish>lambdaUpdate().set(Dish::getStatus,status).in(Dish::getId, (Object[]) ids));
        return R.success("更新状态成功");
    }

    /**
     * 根据id删除菜品（可以批量删除），需要同时删除相关的口味信息
     * @param ids 前端传入的id数组
     * @return
     */
    @DeleteMapping
    //springcache实现数据一致,allEntries = true表示删除所有value开头的键
    @CacheEvict(value = "dish",allEntries = true)
    public R delete(Long[] ids){
        dishService.removeWithDishFlavor(ids);
        return R.success("删除成功");
    }

    /**
     * 根据分类查询菜品，用于添加套餐时选择菜品
     * @param categoryId 分类id
     * @return
     */
    @GetMapping("/list")
    //该方法使用springcache
    @Cacheable(value = "dish",key = "#categoryId")//测试tps为2637，而不使用redis时tps不到400
    public R list(Long categoryId,String name,Integer status){
        log.info("根据分类id为{}查询相关菜品信息",categoryId);
        //原生redis实现缓存菜品
        /*Object redisResult = redisTemplate.opsForValue().get("dish:" + categoryId);
        if (redisResult==null){
            R r = getListFromDataSource(categoryId, name, status);
            redisTemplate.opsForValue().set("dish:" + categoryId,r);
            return r;
        }else {
            return (R) redisResult;
        }*/
        //使用springcache实现时，只需要写查询数据库的相关代码
        return getListFromDataSource(categoryId,name,status);
    }

    private R getListFromDataSource(Long categoryId, String name, Integer status) {
        List<Dish> dishList = dishService.list(Wrappers.<Dish>lambdaQuery()
                .eq(categoryId!=null,Dish::getCategoryId, categoryId)
                .eq(status!=null,Dish::getStatus,status)
                .like(name!=null,Dish::getName, name)
                .orderByDesc(Dish::getSort));
        //C端用户点餐时，用户需要选择口味信息
        List<DishDto> dishDtoList = dishList.stream().map(dish -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish, dishDto);
            List<DishFlavor> dishFlavorList = dishFlavorService.list(Wrappers.<DishFlavor>lambdaQuery()
                    .eq(DishFlavor::getDishId, dish.getId()));
            dishDto.setFlavors(dishFlavorList);
            return dishDto;
        }).collect(Collectors.toList());
        return R.success(dishDtoList);
    }
}
